﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Cudafy;
using Cudafy.Host;
using Cudafy.Translator;

namespace parallel_sema_csharp
{
    public partial class RoughnessFilterDialog : Form
    {
        private Bitmap image;

        public RoughnessFilterDialog()
        {
            InitializeComponent();
        }

        public void LoadImage(Bitmap img)
        {
            image = img;
            pictureBox.Image = image;
        }

        private int[] ImageToIntArray(Bitmap img)
        {
            int image_width = img.Width;
            int image_height = img.Height;
            List<int> matrix = new List<int>();

            for (int i = 0; i < image_height; i += 1)
            {
                for (int j = 0; j < image_width; j += 1)
                {
                    matrix.Add(img.GetPixel(i, j).R);
                    matrix.Add(img.GetPixel(i, j).G);
                    matrix.Add(img.GetPixel(i, j).B);
                }
            }

            return matrix.ToArray();
        }

        /// <summary>
        /// Form Bitmap from array of int values
        /// </summary>
        /// <param name="image_array">Array of int values. Each of them represents one of RGB values</param>
        /// <returns>Bitmap image</returns>
        private Bitmap ImageFromIntArray(int[] image_array)
        {
            return null;
            
        }

        private void test_Click(object sender, EventArgs e)
        {
            roughnessFilterCuda.Execute(ImageToIntArray(image));
        }
    }

    public class roughnessFilterCuda
    {
        private static int N = 512;

        private static int[] c;

        public static void Execute(int [] input_image)
        {
            CudafyModule km = CudafyTranslator.Cudafy();

            GPGPU gpu = CudafyHost.GetDevice(CudafyModes.Target);
            gpu.LoadModule(km);

            // allocate memory on CPU
            int[] a = input_image;
            c = new int[input_image.Length];

            // allocate the memory on the GPU
            int[] dev_a = gpu.Allocate<int>(a);            
            int[] dev_c = gpu.Allocate<int>(c);

            // copy the arrays 'a' and 'b' to the GPU
            gpu.CopyToDevice(a, dev_a);

            // launch add on N threads
            gpu.Launch(N, 1).adder(dev_a, dev_c);

            // copy the array 'c' back from the GPU to the CPU
            gpu.CopyFromDevice(dev_c, c);

            // free the memory allocated on the GPU
            gpu.Free(dev_a);
            gpu.Free(dev_c);
        }

        [Cudafy]
        public static void kernel(GThread thread, int [] input_image, int[] output_image)
        {
            int tid = thread.blockIdx.x;
            int position = tid*3;

            // set RGB of new image pixel
            output_image[position] = 100;
            output_image[position+1] = 100;
            output_image[position+2] = 100;        
        }

    }
}
